﻿

using Grpc.Core;
using IoTClient;
using IotClientService.Models.Lg;
using IotClientService.Models.Lg.Remote;
using IotClientService.Services;
using IotContract.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Extensions;

namespace IotClientService.Handles.lgs;
/// <summary>
/// ocv处理程序
/// 1分周期主动发送 909 获取设备状态
/// 设备状态变更时 设备发送 913 报告状态
/// 作业Mode变更，设备发送917，回918
/// Tray Load，设备发933，回934
/// Tray Unload，设备发937，回938
/// 作业开始，设备发905，回906
/// 作业完成后报告数据，设备发901，回902
/// 作业种类和高度邀请，设备发801，回802
/// 作业再开始/unload，设备发833，回834，正常作业再开始以失败回应。
/// 设备发送的size不对，相互发送981，ret=2
/// 发送的checksum不对，相互发送981，ret=3
/// 有下个作业时，交互看看日志？
/// 
/// 设备通电后，status 从 P变为I,mode 变为0（control)
/// 
/// 设备关闭，先发925然后再发913，status变为 O
/// 
/// 设备异常，发送985
/// 
/// OCV测定作业->trayload933,h934->报告状态run和作业种类申请913,801,h802->作业开始
/// 905,h906->数据报告901,h902->作业完成905,h906->报告状态和trayunload913,937,h938
/// 
/// 
/// </summary>
public class LgHandleOcv : LgHandleBase
{
    public LgHandleOcv(ILgApiService lgCallApiService) : base(lgCallApiService)
    {
    }

    public override IotEquipType EquipType { get; set; } = IotEquipType.OCV;
    /// <summary>
    /// 处理消息
    /// </summary>
    /// <param name="msg"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public override async Task<bool> HandleMsg(LgMsgInfo msg)
    {
        string replyCmd = string.Empty;
        switch(msg.Command)
        {
            // 作业实处理Data报告
            case "901":
                replyCmd = "902";
               await Handle901(msg, replyCmd);
                break;
            // 作业开始/结束报告
            case "905":
                replyCmd = "906";
               await Handle905(msg, replyCmd);
                break;
            // 设备状态报告指示回应
            case "910":
               await Handle910(msg, "910");
                // send 833 

                break;
            // 设备状态报告
            case "913":
               await Handle913(msg, "913");
                
                break;
            // 作业mode报告
            case "917":
                replyCmd = "918";
               await Handle917(msg,replyCmd);
                break;
            // 通信状态报告邀请
            case "925":
                replyCmd = "926";
               await Handle925(msg, replyCmd);
                break;
            // 通信状态报告回应
            case "926":
               await Handle926(msg, "926");
                break;
            // Tray Load报告
            case "933":
                replyCmd = "934";
               await Handle933(msg, replyCmd);
                break;
            // Tray UnLoad报告
            case "937":
                replyCmd = "938";
               await Handle937(msg, replyCmd);
                break;
            // 未知命令,错误
            case "981":
               await Handle981(msg, "981");
                break;
            // 设备Trouble报告
            case "985":
               await Handle985(msg, "985");
                break;
            // 作业种类(OperGroup) 及高度邀请
            case "801":
                replyCmd = "802";
               await Handle801(msg, replyCmd);
                break;
            // 作业再开始 / Tray Unload 邀请 回应
            case "834":
               
               await Handle834(msg, "834");
                break;
            // 设置时间指示
            case "999":
               await Handle999(msg, replyCmd);
                break;
            default:
                // send 981
               await Handle981(msg, "981");
                break;
        }
        return true;
    }
    /// <summary>
    /// 作业实处理Data报告
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle901(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,          
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,

        };
        // 获取作业种类 opengroupid
        // 1 OCV
        string openGroupId = msg.Message.Substring(18, 1);
        // 托盘
        string tray = msg.Message.Substring(19,10);
        // 电芯
        string cells=msg.Message.Substring(39,msg.Message.Length-39-2);

       
        

        // 计算获取电芯数据 47*48个
        var cellCount =(int) (cells.Length / 47);
        List<LgCellOcv> cellOcvs= new List<LgCellOcv>();

        for (int i = 0; i < cellCount; i++)
        {
            var data = cells.Substring(i * 47, 47);
            if (string.IsNullOrWhiteSpace(data)) continue;
            var cellOcv = new LgCellOcv
            {
                Channel = i+1,
                CellType = data.Substring(0, 1),
                Vol = data.Substring(1, 9).To<double>(),
                Ir = data.Substring(10, 9).To<double>(),
                SVol = data.Substring(19, 9).To<double>(),
                Temp = data.Substring(38, 5).To<double>(),
                NgCode = data.Substring(43, 4),
            };
            cellOcvs.Add(cellOcv);
        }
       
       var result=await Api.CommitOcvResult(new LgOcvResultRequest
        {
            Datas = cellOcvs,
            OperGroupID = openGroupId,
            EquipNum = Equip.Num,
            Tray = tray,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType
        });

        if (!result.Success)
        {
            Equip.ExMessage = result.Message;
            return;
        }

        sendMsg.Body = result.Result.Ret.ToString();
        sendMsg.IsSend = true;
        InvokeSend(sendMsg);


    }

    /// <summary>
    /// 作业开始/结束报告
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle905(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,

        };
        // 获取作业种类 opengroupid
        // 1 OCV
        string operGroupId = msg.Message.Substring(18, 1);
        // 托盘
        string tray = msg.Message.Substring(19, 10);

        // S:作业开始  E:作业完成
        string status = msg.Message.Substring(39, 1);

        // 只需要返回ret，其它数据不需要
        var result = await Api.CommitOcvReport(new Models.Lg.Remote.LgOcvReportRequest
        {
            EquipNum=Equip.Num,
            OperGroupID = operGroupId.To<int>(),
            Tray = tray,
            Status = status,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType
        });
        if(!result.Success)
        {
            Equip.ExMessage = result.Message;
            return;
        }
       
        var ret = result.Result.Ret;
        //var curCellCnt = result.CurCellCnt.ToString().PadLeft(3,'0');
        //var limit = result.Limit.ToString().PadLeft(3, '0');
        //var hasNext = result.HasNext;
        sendMsg.Body = $"{ret}";
        sendMsg.IsSend = true;
        Equip.Remark =$"tray:{tray}-{status}";
        InvokeSend(sendMsg);

    }

    
    /// <summary>
    /// Tray Load报告
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle933(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 1,
            
            SeqNo = msg.SeqNo,
            Command = replyCmd,

        };
        // 托盘
        var tray = msg.Message.Substring(18, 10);
        // A:Arrive
        var status = msg.Message.Substring(38, 1);

        Equip.Remark = $"tray load:{tray}-{status}";


        var result = await Api.CommitOcvTrayEnter(new Models.Lg.Remote.LgTrayEnterRequest
        {
            EquipNum=Equip.Num,
            EquipType = this.EquipType,
            Tray = tray,
            ProgramType = Equip.ProgramType
        });
        if (!result.Success) 
        {
            Equip.ExMessage = result.Message;
            return;
        }

        Equip.Obj = tray;

        #region 传输body
        // 0:ok 1:ng  2:bypass
        var ret = result.Result.Ret;
        var model = result.Result.Prod.PadRight(10, ' ');
        #endregion
        sendMsg.Body =$"{ret}{model}";
        sendMsg.IsSend = true;
        InvokeSend(sendMsg);
    }
    /// <summary>
    /// Tray UnLoad报告
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle937(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,

        };
        // 托盘
        var tray = msg.Message.Substring(18, 10);
        // E:End完成
        var status = msg.Message.Substring(38, 1);

        Equip.Remark = $"tray:{tray}-{status} unload";

        var result = await Api.CommitTrayOut(new Models.Lg.Remote.LgTrayOutRequest
        {
            Tray = tray,
            EquipType = this.EquipType,
            EquipNum = Equip.Num,
            ProgramType = Equip.ProgramType
        });
        if(!result.Success) 
        {
            Equip.ExMessage = result.Message;
            return;
        }

        Equip.Obj = "";
        #region 传输body
        // 0:ok 1:ng,再传送后trouble
        int ret = result.Result.Ret;
       
        #endregion
        sendMsg.Body = $"{ret}";
        sendMsg.IsSend = true;
        InvokeSend(sendMsg);
    }
    
    /// <summary>
    /// 作业种类(OperGroup) 及高度邀请
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle801(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 1,
            SeqNo = msg.SeqNo,
            Command = replyCmd,

        };
        // 托盘
        string tray = msg.Message.Substring(18, 10);

        Equip.Remark = $"tray:{tray}";
        // 查询数据

        var result = await Api.GetOcvRecipe(new Models.Lg.Remote.LgOcvReportRequest
        {
            Tray = tray,
            EquipNum = Equip.Num,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType
        });
        if(!result.Success)
        {
            Equip.ExMessage= result.Message;
            return;
        }
        var recipe = result.Result;

        #region 数据构造
        string channelStatus = string.Empty;
        for (int i = 0;i<recipe.Test.Length;i++)
        {
            channelStatus = channelStatus + recipe.Test[i];
        }
        channelStatus = channelStatus.PadRight(48, '1');
        string cellCodes = string.Empty;
        for (int i = 0; i < recipe.Cells.Length; i++)
        {
            cellCodes = cellCodes + recipe.Cells[i];
        }
        cellCodes = cellCodes.PadRight(24 * 48, ' ');
        string ocvResult = "0".PadRight(9 * 48, '0');
        string testTime = "0".PadRight(14 * 48, '0');
        var bodyMsg = $"{recipe.OperGroupID}{recipe.Sequence}{recipe.CellCount}{channelStatus}" +
            $"{cellCodes}{recipe.VoltageUpperLimit.ToString().PadRight(4,' ')}{recipe.VoltageLowerLimit.ToString().PadRight(4,' ')}{recipe.InternalResistanceUpperLimit.ToString().PadRight(6,' ')}{recipe.InternalResistanceLowerLimit.ToString().PadRight(6,' ')}" +
            $"{recipe.ShellPressureUpperLimit.ToString().PadRight(8,' ')}{recipe.ShellPressureLowerLimit.ToString().PadRight(8,' ')}{recipe.KValueUpperLimit.ToString().PadRight(6,' ')}{recipe.KValueLowerLimit.ToString().PadRight(6,' ')}{recipe.OCVResults}{recipe.OCVTimes}"+
            $"{ocvResult}{testTime}";

        sendMsg.Body=bodyMsg;

        sendMsg.IsSend = true;

        InvokeSend(sendMsg);

        #endregion
    }
    /// <summary>
    /// 作业再开始指示回应
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle834(LgMsgInfo msg,string replyCmd)
    {
        // 0:正常再开始 1:再开始 失败（机械性Trouble） 2:在开始失败（没有作业的Tray）
        string ret = msg.Message.Substring(18, 1);

        Equip.Action = ret;

       
        Equip.Remark = $"again:{ret}";
        InvokeSend(msg);
    }

  


}
